﻿using System;

namespace DateGenerator
{
    /// <summary>
    /// Provides multiple ways to generate a random date:
    /// use .Past() to generate a random date in the past
    /// use .Future() to generate a random date in the future
    /// use .Generate() along the LowerBoundary and UpperBoundary to generate a random date withjin a desired range
    /// </summary>
    public class RandomDate
    {
        private Random _r = new Random((int)DateTime.Now.Ticks);

        public DateTime LowerBoundary { get; set; }

        public DateTime UpperBoundary { get; set; }

        /// <summary>
        /// Instantiates a RandomDate with  a random number generator using DateTime.Now.Ticks as the seed
        /// </summary>
        public RandomDate()
        {
            LowerBoundary = DateTime.MinValue;
            UpperBoundary = DateTime.MaxValue;
        }

        public RandomDate(Random r)
        {
            _r = r;

            LowerBoundary = DateTime.MinValue;
            UpperBoundary = DateTime.MaxValue;
        }

        public DateTime Generate()
        {
            return DateTime.Today.AddDays(GenerateRandomDayRange(LowerBoundary, UpperBoundary));
        }       

        private int GenerateRandomDayRange(DateTime rangeFloorBoundary, DateTime rangeCeilingBoundary)
        {
            var d = rangeFloorBoundary - DateTime.Today;
            var daysToLowerBoundary = d.Days +1;

            var u = rangeCeilingBoundary - DateTime.Today;
            var daysToUpperBoundary = u.Days -1;

            //Multiply by minues 1 to create a date in the past
            return _r.Next(daysToLowerBoundary, daysToUpperBoundary);
        }               

        /// <summary>
        /// Generates date in the past. If no lowerboundary is defined then DateTime.MinValue will be used as the bottom boundary
        /// Otherwise the value assigned to LowerBoundary will be used
        /// </summary>
        /// <returns>
        /// A random date in the past
        /// </returns>
        public DateTime Past()
        {
            return DateTime.Today.AddDays(GenerateRandomDayRange(LowerBoundary, DateTime.Today));
        }

        /// <summary>
        /// Generates date in the future. If no upperboundary property is defined then DateTime.MaxValue will be used as the upper boundary
        /// Otherwise the value assigned to UpperBoundary will be used
        /// </summary>
        /// <returns>
        /// A random date in the future
        /// </returns>
        public DateTime Future()
        {
            return DateTime.Today.AddDays(GenerateRandomDayRange(DateTime.Today, UpperBoundary));
        }
    }
}
